#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"

#include "FreeRTOS.h"
#include "task.h"

#include "usart.h"
// #include "buzzer.h"
// #include "hc_sr04.h"
#include "led.h"

static TaskHandle_t xStartTaskHandler;

#if CARBACKING_RADAR
StackType_t puxGetDistanceTask_StackBuffer[128];
StackType_t puxBeepTask_StackBuffer[128];
StaticTask_t pxTCBOfBeepTask;
StaticTask_t pxTCBOfGetDistanceTask;
static float* g_pfDistance;
#endif

#if LED_CHASER
TaskHandle_t xTaskLED1Handler;
TaskHandle_t xTaskLED2Handler;
TaskHandle_t xTaskLED3Handler;
StackType_t puxLED1Task_StackBuffer[32];
StackType_t puxLED2Task_StackBuffer[32];
StackType_t puxLED3Task_StackBuffer[32];
StaticTask_t pxTCBOfLED1Task;
StaticTask_t pxTCBOfLED2Task;
StaticTask_t pxTCBOfLED3Task;
#endif

void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) {
    printf("Stack Overflow in Task: %s\r\n", pcTaskName);
    while (1); // 死循环或系统复位
}

static void StartTask(void* pvParameters) {
    usart0_init();
    led_init();
    // buzzer_init();
    // hc_sr04_init();

    printf("- StartTask\r\n");

    taskENTER_CRITICAL();

    #if LED_CHASER
    xTaskLED1Handler = xTaskCreateStatic(LED1Task, "TaskLED1", 32, NULL, 3, puxLED1Task_StackBuffer, &pxTCBOfLED1Task);
    xTaskLED2Handler = xTaskCreateStatic(LED2Task, "TaskLED2", 32, NULL, 2, puxLED2Task_StackBuffer, &pxTCBOfLED2Task);
    xTaskLED3Handler = xTaskCreateStatic(LED3Task, "TaskLED3", 32, NULL, 1, puxLED3Task_StackBuffer, &pxTCBOfLED3Task);
    // 首次执行先发送任务通知给LED1任务
    xTaskNotifyGive(xTaskLED1Handler);
    #endif

    #if CARBACKING_RADAR
    xTaskCreateStatic(
        fGetDistance, "Get distance task", 128, (void*)&g_pfDistance, 2, puxGetDistanceTask_StackBuffer, &pxTCBOfGetDistanceTask);
    xTaskCreateStatic(
        vBeepTask, "Beep task", 128, (void*)&g_pfDistance, 2, puxBeepTask_StackBuffer, &pxTCBOfBeepTask);
    #endif

    vTaskDelete(xStartTaskHandler);

    taskEXIT_CRITICAL();
}

int main(void) {
    // 设置中断优先级分组为4位抢占优先级，0位响应优先级
    nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);

    // 创建初始化任务
    xTaskCreate(StartTask, "Start task", 128, NULL, 1, &xStartTaskHandler);

    // ??? 为什么这个打印经常不会输出 ???
    printf("Starting task scheduler\r\n");

    vTaskStartScheduler();

    while (1) {
    }
}

#if 0
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

StaticTask_t timer_task_tcb;
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];

void vApplicationGetIdleTaskMemory(
    StaticTask_t** ppxIdleTaskTCBBuffer, StackType_t** ppxIdleTaskStackBuffer, uint32_t* pulIdleTaskStackSize) {
    *ppxIdleTaskTCBBuffer   = &idle_task_tcb;
    *ppxIdleTaskStackBuffer = idle_task_stack;
    *pulIdleTaskStackSize   = configMINIMAL_STACK_SIZE;
}

void vApplicationGetTimerTaskMemory(
    StaticTask_t** ppxTimerTaskTCBBuffer, StackType_t** ppxTimerTaskStackBuffer, uint32_t* pulTimerTaskStackSize) {
    *ppxTimerTaskTCBBuffer   = &timer_task_tcb;
    *ppxTimerTaskStackBuffer = timer_task_stack;
    *pulTimerTaskStackSize   = configTIMER_TASK_STACK_DEPTH;
}
#endif